package org.warm.meaning.x.base.util.bean;

/**
 * 类工具
 *
 * @author SongWarm
 * @date 2024-07-13
 */
public class ClassUtil {

    public static ClassUtil build() {
        return new ClassUtil();
    }

    /**
     * Suffix for array class names: {@code "[]"}.
     */
    public static final String ARRAY_SUFFIX = "[]";

    /**
     * Prefix for internal array class names: {@code "["}.
     */
    private static final String INTERNAL_ARRAY_PREFIX = "[";

    /**
     * Prefix for internal non-primitive array class names: {@code "[L"}.
     */
    private static final String NON_PRIMITIVE_ARRAY_PREFIX = "[L";


    /**
     * 根据类名称获取类
     *
     * @param className 类名称
     * @return 类
     * @throws ClassNotFoundException
     * @author SongWarm
     * @date 2024-07-13
     */
    public Class<?> forName(String className) throws ClassNotFoundException {
        if (null == className || className.isEmpty()) {
            return null;
        }
        return forName(className, false, null);
    }

    /**
     * 根据类名称获取类
     *
     * @param className   类名称
     * @param classLoader 类加载器
     * @return 类
     * @throws ClassNotFoundException
     * @author SongWarm
     * @date 2024-07-13
     */
    public Class<?> forName(String className, ClassLoader classLoader) throws ClassNotFoundException {
        return forName(className, false, classLoader);
    }

    /**
     * 根据类名称获取类
     *
     * @param className   类名称
     * @param initialize  是否初始化(加载)
     * @param classLoader 类加载器
     * @return 类
     * @throws ClassNotFoundException
     * @author SongWarm
     * @date 2024-07-13
     */
    public Class<?> forName(String className, boolean initialize, ClassLoader classLoader) throws ClassNotFoundException {
        if (null == className || className.isEmpty()) {
            return null;
        }
        // "java.lang.String[]" style arrays
        if (className.endsWith(ARRAY_SUFFIX)) {
            String elementClassName = className.substring(0, className.length() - ARRAY_SUFFIX.length());
            Class<?> elementClass = forName(elementClassName, initialize, classLoader);
            return elementClass.arrayType();
        }

        // "[Ljava.lang.String;" style arrays
        if (className.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && className.endsWith(";")) {
            String elementName = className.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), className.length() - 1);
            Class<?> elementClass = forName(elementName, initialize, classLoader);
            return elementClass.arrayType();
        }

        // "[[I" or "[[Ljava.lang.String;" style arrays
        if (className.startsWith(INTERNAL_ARRAY_PREFIX)) {
            String elementName = className.substring(INTERNAL_ARRAY_PREFIX.length());
            Class<?> elementClass = forName(elementName, initialize, classLoader);
            return elementClass.arrayType();
        }

        return Class.forName(className, initialize, classLoader);
    }

}
